package com.example.sakurasay.passwordbook.viewmodels

import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import com.example.sakurasay.passwordbook.data.PasswordBookDatabase
import com.example.sakurasay.passwordbook.data.PasswordBookRepository
import com.example.sakurasay.passwordbook.data.entities.IndependentPasswordEntry
import com.example.sakurasay.passwordbook.data.entities.SharedAccount
import com.example.sakurasay.passwordbook.data.entities.SharedPassword
import com.example.sakurasay.passwordbook.data.relations.SharedPasswordWithAccounts
import com.example.sakurasay.security.EncryptionManager
import com.example.sakurasay.settings.SettingsDataStore
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch

class PasswordBookViewModel(application: Application) : AndroidViewModel(application) {

    private val _isSessionAuthenticated = MutableStateFlow(false)
    val isSessionAuthenticated: StateFlow<Boolean> = _isSessionAuthenticated

    private val repository: PasswordBookRepository
    private val settingsDataStore: SettingsDataStore
    private val encryptionManager: EncryptionManager

    init {
        val database = PasswordBookDatabase.getDatabase(application)
        val independentPasswordDao = database.independentPasswordDao()
        val sharedPasswordDao = database.sharedPasswordDao()
        encryptionManager = EncryptionManager(application)
        repository = PasswordBookRepository(independentPasswordDao, sharedPasswordDao, encryptionManager)
        settingsDataStore = SettingsDataStore(application)
    }

    // Independent Passwords
    val allIndependentPasswords: Flow<List<IndependentPasswordEntry>> = repository.allIndependentPasswords
    fun searchIndependentPasswords(query: String): Flow<List<IndependentPasswordEntry>> = repository.searchIndependentPasswords(query)
    fun insertIndependentPassword(password: IndependentPasswordEntry) = viewModelScope.launch { repository.insertIndependentPassword(password) }
    fun updateIndependentPassword(password: IndependentPasswordEntry) = viewModelScope.launch { repository.updateIndependentPassword(password) }
    fun deleteIndependentPassword(password: IndependentPasswordEntry) = viewModelScope.launch { repository.deleteIndependentPassword(password) }

    // Shared Passwords
    val allSharedPasswords: Flow<List<SharedPassword>> = repository.getAllSharedPasswords()
    fun getAccountsForSharedPassword(passwordId: Int): Flow<List<SharedAccount>> = repository.getAccountsForSharedPassword(passwordId)
    fun searchSharedPasswords(query: String): Flow<List<SharedPassword>> = repository.searchSharedPasswords(query)
    fun insertSharedPassword(password: SharedPassword, accounts: List<SharedAccount>) = viewModelScope.launch { repository.insertSharedPassword(password, accounts) }
    fun updateSharedPassword(password: SharedPassword, accounts: List<SharedAccount>) = viewModelScope.launch { repository.updateSharedPassword(password, accounts) }
    fun deleteSharedPassword(password: SharedPassword) = viewModelScope.launch { repository.deleteSharedPassword(password) }

    val sharedPasswordsWithAccounts: Flow<List<SharedPasswordWithAccounts>> = repository.getSharedPasswordsWithAccounts()

    // Settings
    val passwordBookMode: Flow<Int> = settingsDataStore.passwordBookMode
    fun setPasswordBookMode(modeIndex: Int) {
        viewModelScope.launch {
            settingsDataStore.savePasswordBookMode(modeIndex)
        }
    }

    fun setSessionAuthenticated(isAuthenticated: Boolean) {
        _isSessionAuthenticated.value = isAuthenticated
    }
}

class PasswordBookViewModelFactory(private val application: Application) : ViewModelProvider.Factory {
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(PasswordBookViewModel::class.java)) {
            @Suppress("UNCHECKED_CAST")
            return PasswordBookViewModel(application) as T
        }
        throw IllegalArgumentException("Unknown ViewModel class")
    }
}